òɾۿûѧϰʹá
ԭַhttps://www.joinquant.com/post/14323

ԭһ˵ʽ鵽ԭĺ߽ۡ


ԭĲԴ£

#˫߲
# 2015-01-01  2016-03-08, 2000000, ÿ
# https://www.joinquant.com/post/ae7b7f898c798186ff05523d385f8561?f=stydy&m=algorithm

'''
================================================================================
زǰ
================================================================================
'''
#زǰҪ
def initialize(context):
    set_params()    #1ò߲
    set_variables() #2м
    set_backtest()  #3ûز
    
    g.long_day = 60 # 
    g.short_day = 120 # ̾
    
#1
#òԲ
def set_params():
    g.tc=15  # Ƶ
    g.N=4 # ֲĿ
    g.security = ["000001.XSHE","000002.XSHE","000006.XSHE","000007.XSHE","000009.XSHE"]#ùƱ

#2
#м
def set_variables():
    return

#3
#ûز
def set_backtest():
    set_option('use_real_price', True) #ʵ۸
    log.set_level('order', 'error')

'''
================================================================================
ÿ쿪ǰ
================================================================================
'''
#ÿ쿪ǰҪ
def before_trading_start(context):
    set_slip_fee(context) 

#4 
# ݲͬʱû
def set_slip_fee(context):
    # Ϊ0
    # set_slippage(FixedSlippage(0)) 
    
    ### Ʊ趨 ###
    # ƱÿʽʱǣʱӶ֮ʱӶ֮ǧ֮һӡ˰, ÿʽӶͿ5Ǯ
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')

'''
================================================================================
ÿ콻ʱ
================================================================================
'''
def handle_data(context, data):
    # ʽȷΪg.NݣΪÿֻƱ
    capital_unit = context.portfolio.portfolio_value/g.N
    toSell = signal_stock_sell(context,data)
    toBuy = signal_stock_buy(context,data)
    # ִڳʽ
    for i in range(len(g.security)):
        if toSell[i]==1:
            order_target_value(g.security[i],0)
    # ִ
    for i in range(len(g.security)):
        if toBuy[i]==1:
            order_target_value(g.security[i],capital_unit)  
    if not (1 in toBuy) or (1 in toSell):
        # log.info("޲")
        send_message("޲")


#5
#ź
#룺context, data
#sell - list
def signal_stock_sell(context,data):
    sell = [0]*len(g.security)
    for i in range(len(g.security)):
    # ָƶߵֵ賤60죬1(ǰһ̼)
        (ema_long_pre,ema_long_now) = get_EMA(g.security[i],g.long_day,data)
        (ema_short_pre,ema_short_now) = get_EMA(g.security[i],g.short_day,data)
        # ̾ߴ´ԽߣΪźţ
        if ema_short_now < ema_long_now and ema_short_pre > ema_long_pre and context.portfolio.positions[g.security[i]].sellable_amount > 0:
            sell[i]=1
    return sell
        

#6
#ź
#룺context, data
#buy - list
def signal_stock_buy(context,data):
    buy = [0]*len(g.security)
    for i in range(len(g.security)):
    # ָƶߵֵ賤60죬1(ǰһ̼)
        (ema_long_pre,ema_long_now) = get_EMA(g.security[i],g.long_day,data)
        (ema_short_pre,ema_short_now) = get_EMA(g.security[i],g.short_day,data)
        # ̾ߴϴԽߣΪźţ
        if ema_short_now > ema_long_now and ema_short_pre < ema_long_pre and context.portfolio.positions[g.security[i]].sellable_amount == 0 :
            buy[i]=1
    return buy

#7
# ƶƽ
# 룺Ʊ-ַƶƽ-
# ƽֵ-
def get_MA(security_code,days):
    # ǰdaysݣAPI
    a=attribute_history(security_code, days, '1d', ('close'))
    # һֲsum
    sum=0
    # ǰdays̼۽
    for i in range(1,days+1):
        sum+=a['close'][-i]
    # ֮ͿԵĵõƽֵ
    return sum/days

#8
# ָƶƽ
# 룺Ʊ-ַƶָƽ-data
# ƶָƽ-
def get_EMA(security_code,days,data):
    # ֻһĻ,ǰһ̼۾ƶƽ
    if days==1:
    # ǰ̼ݣһΪһڵƶƽֵһΪڵƶƽֵ
        t = attribute_history(security_code, 2, '1d', ('close'))
        return t['close'][-2],t['close'][-1]
    else:
    # ȫֱg.EMAsڵĻһֵ͵ı¼ѾEMAֵ
        if 'EMAs' not in dir(g):
            g.EMAs={}
        # ֵĹؼùƱΨһȷⲻͬƱָ߲ͬƶƽŪһ
        key="%s%d" %(security_code,days)
        # ؼִڣ˵֮ǰѾEMAˣֱӵ
        if key in g.EMAs:
            #alphaֵ
            alpha=(days-1.0)/(days+1.0)
            # ǰһEMAǱˣ
            EMA_pre=g.EMAs[key]
            # EMA
            EMA_now=EMA_pre*alpha+data[security_code].close*(1.0-alpha)
            # дµEMAֵ
            g.EMAs[key]=EMA_now
            # ûͽEMAֵ
            return (EMA_pre,EMA_now)
        # ؼֲڣ˵֮ǰûмEMAҪʼ
        else:
            # daysƶƽ
            ma=get_MA(security_code,days) 
            # ƽڣNaNĻôѾ㹻ݿԶEMAʼ
            if not(isnan(ma)):
                g.EMAs[key]=ma
                # ΪոճʼǰһڵEMA
                return (float("nan"),ma)
            else:
                # ƶƽݲdays죬ֻ÷NaNֵ
                return (float("nan"),float("nan"))

'''
================================================================================
ÿ̺
================================================================================
'''
# ÿ̺Ҫ飨вҪ
def after_trading_end(context):
    #õгɽ¼
    trades = get_trades()
    for _trade in trades.values():
        log.info('ɽ¼'+str(_trade))
    log.info('##############################################################')